#include "StdAfx.h"
#include "decMesh3.h"
#include <set>

namespace ds3{

	decMesh3::decMesh3(void)
	{
	}


	decMesh3::~decMesh3(void)
	{
	}

	void decMesh3::checkUpdate()
	{
		computeBoundBox();
	}

	bool decMesh3::isValidShape() const
	{
		return countFace()>0 && countVertices()>0;
	}

	const GeBoundBox3d& decMesh3::getBoundBox() const
	{
		return m_bbox;
	}

	decMesh3& decMesh3::transformBy( const GeMatrix3d&tm )
	{
		return *this;
	}
	void computeNormal(
		const GePoint3f&p1
		,const GePoint3f&p2
		,const GePoint3f&p3
		,GeVector3f&nor)
	{
		GePoint3d pp1(p1.x,p1.y,p1.z);
		GePoint3d pp2(p2.x,p2.y,p2.z);
		GePoint3d pp3(p3.x,p3.y,p3.z);
		GeVector3d v1=pp2-pp1;
		GeVector3d v2=pp3-pp1;
		GeVector3d v3=v1.crossProduct(v2);
		v3.normalize();
		nor.set(v3.x,v3.y,v3.z);
	}
	void decMesh3::setSmoothGroup( int num,const DWORD*arrGroup )
	{
		ASSERT(num==countFace() && arrGroup);
		/*
		static std::vector<MeshVertex>arr_vts;
		arr_vts.clear();
		MeshVertex*vts=&m_arrVert[0];
		int numVert=countVertices();
		int numFace=countFace();
		GeVector3f nor;
		for(int i=0;i<numFace;++i)
		{
			const MeshTriFace&fc=m_arrFace[i];
			computeNormal(
				(GePoint3f&)vts[fc.vert[0]].vert,
				(GePoint3f&)vts[fc.vert[1]].vert,
				(GePoint3f&)vts[fc.vert[2]].vert,
				nor);
			for(int j=0;j<3;++j)
			{
				MeshVertex pt;
				pt=vts[fc.vert[j]];
				pt.setNormal(nor);
				arr_vts.push_back(pt);
			}
		}
		m_arrVert2=arr_vts;
		*/
		std::set<DWORD>set_gp;
		for(int i=0;i<num;++i)
		{
			set_gp.insert(arrGroup[i]);
		}
		MeshVertex*vts=&m_arrVert[0];
		int numVert=countVertices();
		for(int i=0;i<numVert;++i)
		{
			vts[i].setNormal(GeVector3f(0,0,0));
		}
		auto add_vert_normal=[&](int ivert,const GeVector3f&nor)
		{
			GeVector3f nor1=vts[ivert].normal();
			nor1+=nor;
			nor1.normalize();
			vts[ivert].setNormal(nor1);
		};
		int numFace=countFace();
		GeVector3f nor;
		for(int i=0;i<numFace;++i)
		{
			const MeshTriFace&fc=m_arrFace[i];
			computeNormal(
				(GePoint3f&)vts[fc.vert[0]].vert,
				(GePoint3f&)vts[fc.vert[1]].vert,
				(GePoint3f&)vts[fc.vert[2]].vert,
				nor);
			add_vert_normal(fc.vert[0],nor);
			add_vert_normal(fc.vert[1],nor);
			add_vert_normal(fc.vert[2],nor);
		}
	}

	int decMesh3::countFace() const
	{
		return m_arrFace.size();
	}

	int decMesh3::countVertices() const
	{
		return m_arrVert.size();
	}

	void decMesh3::computeBoundBox()
	{
		m_bbox.setEmpty();
		int num=countVertices();
		for(int i=0;i<num;++i)
		{
			const GePoint3f&pt=m_arrVert[i].vertex();
			if(i==0)
			{
				m_bbox.set(GePoint3d(pt.x,pt.y,pt.z));
			}
			else
			{
				m_bbox.extend(GePoint3d(pt.x,pt.y,pt.z));
			}
		}
	}

	MeshVertex& MeshVertex::set( const GePoint3f&pt,const GeVector3f&nor1,const GeVector2f&uv)
	{
		vert[0]=pt.x;
		vert[1]=pt.y;
		vert[2]=pt.z;
		nor[0]=nor1.x;
		nor[1]=nor1.y;
		nor[2]=nor1.z;
		tex[0]=uv.x;
		tex[1]=uv.y;
		return *this;
	}

	MeshVertex& MeshVertex::setNormal( const GeVector3f&nor1 )
	{
		nor[0]=nor1.x;
		nor[1]=nor1.y;
		nor[2]=nor1.z;
		return *this;
	}

	GeVector3f& MeshVertex::normal()
	{
		return (GeVector3f&)nor;
	}

	GePoint3f& MeshVertex::vertex()
	{
		return (GePoint3f&)vert;
	}

}